<?php

/*
Copyright 2009-2011 Sam Weiss
All Rights Reserved.

This file is part of Spark/Plug.

Spark/Plug is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

if (!defined('spark/plug'))
{
	header('HTTP/1.1 403 Forbidden');
	exit('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><html><head><title>403 Forbidden</title></head><body><h1>Forbidden</h1><p>You don\'t have permission to access the requested resource on this server.</p></body></html>');
}

// -----------------------------------------------------------------------------

class _SparkDateTime
{
	private static $_time_zone_map = array
	(
		'US/Hawaii' => 'Pacific/Honolulu',
		'US/Alaska' => 'America/Juneau',
		'US/Pacific' => 'America/Los_Angeles',
		'US/Arizona' => 'America/Phoenix',
		'US/Mountain' => 'America/Denver',
		'US/Central' => 'America/Chicago',
		'US/Eastern' => 'America/New_York',
	);

	private static $_is_5_3_0;
	private $_tz;
	private $_dt;

	// --------------------------------------------------------------------------

	public static function mapTimeZone($timeZone)
	{
		if (isset(self::$_time_zone_map[$timeZone]))
		{
			return self::$_time_zone_map[$timeZone];
		}
		return $timeZone;
	}

	// --------------------------------------------------------------------------

	public function __construct($dateTimeString = 'now', $timezone = 'UTC')
	{
		if (!isset(self::$_is_5_3_0))
		{
			self::$_is_5_3_0 = (version_compare(PHP_VERSION, '5.3.0') >= 0);
		}
		$this->set($dateTimeString, $timezone);
	}

	// --------------------------------------------------------------------------

	public function set($dateTimeString, $timezone = NULL)
	{
		if ($timezone)
		{
			$this->_tz = $timezone;
		}
		elseif (!$this->_tz)
		{
			$this->_tz = 'UTC';
		}

		$this->_dt = new DateTime($dateTimeString, new DateTimeZone(self::mapTimeZone($this->_tz)));

		return $this;
	}

	// --------------------------------------------------------------------------

	public function setTimeZone($timezone)
	{
		$this->_dt->setTimezone(new DateTimeZone(self::mapTimeZone($this->_tz = $timezone)));
		return $this;
	}

	// --------------------------------------------------------------------------

	public function addSeconds($n)
	{
		if (self::$_is_5_3_0)
		{
			if ($n < 0)
			{
				$n *= -1;
				$this->_dt->sub(new DateInterval('PT'.$n.'S'));
			}
			else
			{
				$this->_dt->add(new DateInterval('PT'.$n.'S'));
			}
		}
		else
		{
			$current = getdate($this->getTimestamp());
			$ts = mktime($current['hours'], $current['minutes'], $current['seconds'] + $n, $current['mon'], $current['mday'], $current['year']);
			$saveTZ = $this->_tz;
			$this->set('@'.$ts, 'UTC');
			$this->setTimeZone($saveTZ);
		}
		return $this;
	}

	// --------------------------------------------------------------------------

	public function addMinutes($n)
	{
		if (self::$_is_5_3_0)
		{
			if ($n < 0)
			{
				$n *= -1;
				$this->_dt->sub(new DateInterval('PT'.$n.'M'));
			}
			else
			{
				$this->_dt->add(new DateInterval('PT'.$n.'M'));
			}
		}
		else
		{
			$current = getdate($this->getTimestamp());
			$ts = mktime($current['hours'], $current['minutes'] + $n, $current['seconds'], $current['mon'], $current['mday'], $current['year']);
			$saveTZ = $this->_tz;
			$this->set('@'.$ts, 'UTC');
			$this->setTimeZone($saveTZ);
		}
		return $this;
	}

	// --------------------------------------------------------------------------

	public function addHours($n)
	{
		if (self::$_is_5_3_0)
		{
			if ($n < 0)
			{
				$n *= -1;
				$this->_dt->sub(new DateInterval('PT'.$n.'H'));
			}
			else
			{
				$this->_dt->add(new DateInterval('PT'.$n.'H'));
			}
		}
		else
		{
			$current = getdate($this->getTimestamp());
			$ts = mktime($current['hours'] + $n, $current['minutes'], $current['seconds'], $current['mon'], $current['mday'], $current['year']);
			$saveTZ = $this->_tz;
			$this->set('@'.$ts, 'UTC');
			$this->setTimeZone($saveTZ);
		}
		return $this;
	}

	// --------------------------------------------------------------------------

	public function addDays($n)
	{
		if (self::$_is_5_3_0)
		{
			$this->_dt->add(new DateInterval('P'.$n.'D'));
		}
		else
		{
			$current = getdate($this->getTimestamp());
			$ts = mktime($current['hours'], $current['minutes'], $current['seconds'], $current['mon'], $current['mday'] + $n, $current['year']);
			$saveTZ = $this->_tz;
			$this->set('@'.$ts, 'UTC');
			$this->setTimeZone($saveTZ);
		}
		return $this;
	}

	// --------------------------------------------------------------------------

	public function addMonths($n)
	{
		if (self::$_is_5_3_0)
		{
			$this->_dt->add(new DateInterval('P'.$n.'M'));
		}
		else
		{
			$current = getdate($this->getTimestamp());
			$ts = mktime($current['hours'], $current['minutes'], $current['seconds'], $current['mon'] + $n, $current['mday'], $current['year']);
			$saveTZ = $this->_tz;
			$this->set('@'.$ts, 'UTC');
			$this->setTimeZone($saveTZ);
		}
		return $this;
	}

	// --------------------------------------------------------------------------

	public function addYears($n)
	{
		if (self::$_is_5_3_0)
		{
			$this->_dt->add(new DateInterval('P'.$n.'Y'));
		}
		else
		{
			$current = getdate($this->getTimestamp());
			$ts = mktime($current['hours'], $current['minutes'], $current['seconds'], $current['mon'], $current['mday'], $current['year'] + $n);
			$saveTZ = $this->_tz;
			$this->set('@'.$ts, 'UTC');
			$this->setTimeZone($saveTZ);
		}
		return $this;
	}

	// --------------------------------------------------------------------------

	public function format($format = 'Y-m-d H:i:s')
	{
		return $this->_dt->format($format);
	}

	// --------------------------------------------------------------------------

	public function ymd($sep = '-')
	{
		return $this->format("Y{$sep}m{$sep}d");
	}

	// --------------------------------------------------------------------------

	public function ymdhms($sep1= '-', $sep2 = ':')
	{
		return $this->format("Y{$sep1}m{$sep1}d H{$sep2}i{$sep2}s");
	}

	// --------------------------------------------------------------------------

	public function strformat($format = '%Y-%m-%d %T')
	{
		$ts = $this->getTimestamp() + $this->_dt->getOffset();
		$format = str_replace(array('%z','%Z'), $this->_tz, $format);
		return strftime($format, $ts);
	}

	// --------------------------------------------------------------------------

	public function getTimestamp()
	{
		return 
			self::$_is_5_3_0
				? $this->_dt->getTimestamp()
				: $this->_dt->format('U');
	}

	// --------------------------------------------------------------------------
}
